home *** CD-ROM | disk | FTP | other *** search
- /* Document.C
- *
- * Of all the parameters, those in the derived class Document are probably
- * the most basic. Calls to class Document routines can usually be resolved
- * directly into some simple PostScript output involving no nesting.
- *
- * Copyright 1992 Jonathan Monsarrat. Permission given to freely distribute,
- * edit and use as long as this copyright statement remains intact.
- *
- */
-
- #include "Operator.h"
- #include "Global.h"
- #include "Document.h"
- #include "Font.h"
- #include <string.h>
- #include <stdio.h>
-
- float Document::start_page;
-
- Document::Document()
- {
- for(int x=0; x < LastType; x++)
- values[x] = 0.0;
- begin_command[0] = '\0';
- start_page = 0;
- }
-
- Document::Document(Document *base)
- {
- for(int x=0; x < LastType; x++)
- values[x] = base->values[x];
- strcpy(begin_command, base->begin_command);
- }
-
- Param *Document::copy()
- {
- Document *doc = new Document(this);
- doc->set(End, 0.0, begin_command);
- return doc;
- }
-
- int Document::set(int subtype, float value, char *replacestr)
- {
- switch(subtype) {
- case Begin:
- strcpy(begin_command,replacestr);
- break;
- case DocumentStart:
- values[DocumentStart] = value;
- break;
- case End:
- if(strcmp(begin_command,replacestr) != 0) {
- char message[MAXSTRING];
- sprintf(message, "\\end{%s} does not match a \\begin{%s}",
- replacestr, begin_command);
- Global::files->fatal_error(message);
- }
- begin_command[0] = '\0';
- break;
- case NewLine:
- Operator::do_vspace(0, 0,
- Global::stack->get(Environment::PLength, Length::Parameter,
- "\\baselineskip"), "");
- break;
- case StartPage:
- start_page = value;
- break;
- case Stealth:
- if(!Stack::get(Environment::PDocument, Document::Comment, ""))
- Global::files->fatal_error(
- "\\stealth must go on a comment line to be compatible with LaTeX");
- values[Stealth] = value;
- break;
- default:
- values[subtype] = value;
- break;
- }
- return TRUE;
- }
-
- float Document::get(int subtype, char *comparestr)
- {
- switch(subtype) {
- case CloseBrace:
- if(begin_command[0] != '\0') {
- char message[MAXSTRING];
- sprintf(message, "\\begin{%s} closed with '}' instead of \\end{%s}",
- begin_command, begin_command);
- Global::files->fatal_error(message);
- }
- break;
- case Begin:
- case End:
- return !strcmp(comparestr, begin_command);
- case ShutDown: // only happens in Stack::shutdown()
- if(begin_command[0] != '\0') {
- char message[MAXSTRING];
- sprintf(message, "\\begin{%s} not closed at end of input",
- begin_command);
- Global::files->fatal_error(message);
- }
- break;
- case StartPage:
- return start_page;
- default:
- break;
- }
- return values[subtype];
- }
-
- void Document::revert(Param *from)
- {
- for(int subtype=0; subtype < LastType; subtype++) {
- switch(subtype) {
- case End:
- case Begin:
- case CloseBrace:
- case ShutDown:
- break;
- default:
- if(values[subtype] != from->get(subtype,"revert"))
- postscript_set(subtype);
- break;
- }
- }
- }
-
- void Document::postscript_set(int subtype)
- {
- switch(subtype) {
- case DocumentStart: // No postscript output needed
- default:
- break;
- }
- }
-
- /* Begins an environment */
- void Document::begin(int paramtype, int subtype, float value,
- char *replacestr)
- {
- Token openbrace;
- if(!openbrace.match("{"))
- Global::files->fatal_error("Expecting '{' after \\begin statement");
-
- Token command;
- if(command.match("}"))
- Global::files->
- fatal_error("Expecting command before closing '}' in \\begin");
-
- if(!command.match("stealth"))
- Stack::push(paramtype, subtype, value, replacestr);
-
- Token closebrace;
- if(!closebrace.match("}"))
- Global::files->
- fatal_error("More than one word before closing '}' in \\begin");
-
- char begin_command[MAXSTRING];
- strcpy(begin_command,"\\"); // Make the token "foo" into command "\foo"
- char *tokentext = command.get_text();
-
- // One of the values in parameter "Document" keeps track of the
- // command executed by the last \begin command, to that when the \end
- // command is called, we can check it against the \begin command.
- if(!command.match("stealth"))
- Stack::set(Environment::PDocument, Document::Begin, 0.0, tokentext);
-
- strcat(begin_command,tokentext);
- command.make_text(begin_command);
- command.handle(); // Handle the command.
-
- }
-
- /* Ends an environment */
- void Document::end(int, int, float, char *)
- {
- Token openbrace;
- if(!openbrace.match("{"))
- Global::files->fatal_error("Expecting '{' after \\end");
-
- Token command; // Assume it's the same as the last begin command
- if(command.match("}"))
- Global::files->fatal_error(
- "Expecting command before '}' in \\end statement");
- if(!command.match("stealth")) {
- char *begin_command = command.get_text();
- Stack::set(Environment::PDocument, Document::End, 0.0, begin_command);
- }
-
- Token closebrace;
- if(!closebrace.match("}"))
- Global::files->
- fatal_error("More than one word before closing '}' in \\end");
-
- if(command.match("stealth"))
- Stack::set(Environment::PDocument, Document::Stealth, 0.0, "");
- else
- Stack::pop(0, Document::End, 0.0, "");
- }
-
- void Document::documentstyle(int, int, float, char *)
- {
- Token openbrace;
- if(openbrace.match("[")) {
- Global::files->comma_delimiter(TRUE); // Commas are valid delimiters
-
- for(Token option = Token(); !option.match("]"); option = Token()) {
- if(option.match(""))
- continue;
-
- if(option.match("10pt")) {
- // Do nothing. This is the default.
- } else if(option.match("11pt")) {
- // Makes 11 point type the default size
- Stack::set(Environment::PFont, Font::Base11pt, 0.0, "");
- Stack::set(Environment::PLength, Length::Parameter, 23.5,
- "\\bigskipamount");
- Stack::set(Environment::PLength, Length::Parameter, 18.6,
- "\\medskipamount");
- Stack::set(Environment::PLength, Length::Parameter, 16.0,
- "\\smallskipamount");
- } else if(option.match("12pt")) {
- // Makes 12 point type the default size
- Stack::set(Environment::PFont, Font::Base12pt, 0.0, "");
- Stack::set(Environment::PLength, Length::Parameter, 25.7,
- "\\bigskipamount");
- Stack::set(Environment::PLength, Length::Parameter, 20.3,
- "\\medskipamount");
- Stack::set(Environment::PLength, Length::Parameter, 17.4,
- "\\smallskipamount");
- } else if(option.match("twoside")) {
- // Formats the output for printing on both sides of a page
- Global::files->warning("twoside option not supported in LameTeX");
- } else if(option.match("twocolumn")) {
- // Makes two-column pages
- Global::files->warning(
- "twocolumn option not supported in LameTeX");
- } else if(option.match("titlepage")) {
- // article option only!
- Global::files->warning("twoside option not supported in LameTeX");
- } else if(option.match("openbib")) {
- Global::files->warning("openbib option not supported in LameTeX");
- } else if(option.match("leqno")) {
- Global::files->warning("leqno option not supported in LameTeX");
- } else if(option.match("fleqn")) {
- Global::files->warning("fleqn option not supported in LameTeX");
- } else
- Global::files->warning("Unknown option in \\documentstyle[]");
- }
- Global::files->comma_delimiter(FALSE); // Commas not valid delimiters
- openbrace = Token(); // An openbrace should come now
- }
-
- if(openbrace.match("{")) {
- } else
- Global::files->fatal_error("Expecting '{' or '[' in \\documentstyle");
-
- Token style;
- if(style.match("}"))
- Global::files->fatal_error(
- "Expecting style before '}' in \\documentstyle");
-
- if(style.match("article")) {
- // the article style does not have a \chapter command
- // the default pagestyle is plain
- // \flushbottom if [twoside], else \raggedbottom
- // numbers figures and tables consecutively throughout
- // if [titlepage] is used \abstract looks like normal article paragraph
- // \parskip is zero
- } else if(style.match("book")) {
- // \flushbottom
- // numbers figures and tables by chapter
- // there is no \abstract environment
- // \parskip is zero
- } else if(style.match("letter")) {
- // same as the \letter command. Very complex.
- // special commands \opening, \address, \signature, \cc, \encl, etc.
- // \raggedbottom
- // \parskip is non-zero
- Global::files->warning("letter style not supported in LameTeX");
- } else if(style.match("report")) {
- // the default pagestyle is plain
- // \flushbottom if [twoside], else \raggedbottom
- // numbers figures and tables by chapter
- // \abstract is placed on a separate page
- // \parskip is zero
- } else if(style.match("slides")) {
- // same as the \slide command. Very complex.
- Global::files->warning("slides style not supported in LameTeX");
- } else
- Global::files->warning(
- "Unknown style in \\documentstyle. User-defined styles not supported.");
-
- Token closebrace;
- if(!closebrace.match("}"))
- Global::files->fatal_error(
- "Only one word allowed between braces in \\documentstyle");
- }
-